home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / packet / p_tapr / tnchst / blp.c < prev    next >
Text File  |  1992-03-16  |  22KB  |  832 lines

  1. /***** BINARY LINK PROTOCOL   SOFTWARE (c) 1990-91 Howard Goldstein N2WX***/
  2. /* all rights reserved.  permission for non-commercial amateur use
  3. /* granted */
  4.  
  5. #include   "blp.inc"
  6.  
  7.     /*** global variables ***/
  8.  
  9.                     /* storage for blp control blocks */
  10.     struct    blpcb_struct    blp_cb[NLINKS];
  11.  
  12.  
  13.  
  14.  
  15.  
  16. void cdecl blp_init()                /* call on init */
  17. {
  18.     int x;
  19.  
  20.     for ( x = 0 ; x < NLINKS ; x++ )    /* set up all of em */
  21.     {
  22.         blp_cb[x].bsstate = BSIDLE ;    /* bsstate to idle */
  23.         blp_cb[x].timer   = (-1)   ;    /* stop timer */
  24.     }
  25. }
  26.  
  27.  
  28.     /* set timer to expired and zero the retry counter - called on
  29.        state change */
  30. void cdecl  blp_timer_retry_reset( blpcb )
  31. struct blpcb_struct *blpcb;
  32. {
  33.     blpcb->timer = 0 ;        /* causes immediate expiration */
  34.     blpcb->retry_count = 0 ;
  35. }
  36.  
  37. void cdecl blp_event( event, blpcb, bframe, len)
  38. byte  event;        /* as defined by preproc directives */
  39. struct blpcb_struct *  blpcb;
  40. struct bframe_struct *  bframe;    /* ptr to frame, if any associated w/ event */
  41. word  len;            /* len "    " */
  42. {
  43.     byte    nstate;
  44.             /* these are the state tables; included later, must
  45.                be identified here */
  46.     extern    struct state_entry blps_table[][NSEVENTS],
  47.                    blpd_table[][NDEVENTS];
  48.  
  49.     void    (*hdlr) (struct blpcb_struct *, struct bframe_struct *,
  50.              word );
  51.  
  52.                 /* supervisory event? */
  53.     if ( event < FIRST_DATA_EVENT )
  54.     {
  55.             /* set up local vars w/ results of lookup */
  56.         nstate = blps_table[blpcb->bsstate - 1][event].newstate ;
  57.         hdlr = blps_table[blpcb->bsstate - 1][event].action_handler ;
  58.  
  59. #if BLP_EVENT_TRACE
  60.     /* display events */
  61.  printf(" Chan=%d SEvent=%d Sstate=%d Dstate=%d Newstate=%d hdlr=%x\n",
  62.         blpcb->local_chan, event,
  63.         blpcb->bsstate,blpcb->bdstate, nstate, hdlr );
  64. #endif
  65.  
  66.                 /* if new state is mentioned and diff from the
  67.                    current state */
  68.         if ( nstate && nstate != blpcb->bsstate)
  69.         {
  70.             blp_timer_retry_reset( blpcb );    /* reset timer, try */
  71.             blpcb->bsstate = nstate ;    /* change state */
  72.         }
  73.  
  74.         if ( hdlr )    /* if a handler was defined */
  75.             (*hdlr) (blpcb,bframe,len) ;    /* then run it */
  76.  
  77.             /** note assumption in collission handler
  78.                 and loopback requriing nstate change be
  79.                 done prior to handler execution, as above **/
  80.  
  81.     }
  82.     else    /* data event */
  83.     {
  84.                 /* must be in supvy data state to operate
  85.                    on data events */
  86.            if ( blpcb->bsstate == BSDATA )          /* if in data state */
  87.        {
  88.                 event -= FIRST_DATA_EVENT ;    /* take bias out - start
  89.                            counting at 0 */
  90. /** note quite similar to above; may want to compress later **/
  91.         nstate = blpd_table[blpcb->bdstate - 1][event].newstate ;
  92.         hdlr = blpd_table[blpcb->bdstate - 1][event].action_handler ;
  93.  
  94. #if BLP_EVENT_TRACE
  95.     /* display events */
  96.  printf(" Chan=%d DEvent=%d Sstate=%d Dstate=%d Newstate=%d hdlr=%x\n",
  97.         blpcb->local_chan, event,
  98.         blpcb->bsstate,blpcb->bdstate, nstate, hdlr );
  99. #endif
  100.                 /* if new state is mentioned and diff from the
  101.                    current state */
  102.         if ( nstate && nstate != blpcb->bdstate)
  103.         {
  104.             blp_timer_retry_reset( blpcb );    /* reset timer, try */
  105.             blpcb->bdstate = nstate ;    /* change state */
  106.         }
  107.  
  108.         if ( hdlr )    /* if a handler was defined */
  109.             (*hdlr) (blpcb,bframe,len) ;    /* then run it */
  110.  
  111.  
  112.         } /* endif in data state */
  113.     } /* endif data event */
  114.  
  115. }
  116.  
  117.     /* call on timer tick intervals - updates and signals expiration
  118.        events */
  119. void cdecl  blp_timer_tick()
  120. {
  121.     byte    x;
  122.  
  123.     for ( x = 0 ; x < NLINKS ; x++ )    /* traverse all blps */
  124.     {
  125.         if ( blp_cb[x].bsstate != BSIDLE )
  126.             blp_event( LUNBUSY, &blp_cb[x], NULL, 0);
  127.             
  128.         if ( blp_cb[x].bsstate != BSIDLE     /* if not idle and */
  129.           && blp_cb[x].timer >= 0 )        /* timer not stopped */
  130.         {                /* then count time pd - */
  131.             if ( ( --blp_cb[x].timer < 1 ) ) /* if now expired */
  132.             {                /*   then signal event*/
  133.  
  134.                 /* force timer to stay expired */
  135.               --blp_cb[x].timer ;
  136.  
  137.                 /* count retry */
  138.               if ( blp_cb[x].retry_count++ == BLP_MAX_TRIES )
  139.                     /* if retry lim excdd then LRETRY event*/
  140.                 blp_event( LRETRY, &blp_cb[x], NULL, 0 );
  141.               else
  142.                                  /* else TIMER event, */
  143.                         /* type event depends on
  144.                            whether in supvy state or
  145.                            not */
  146.                   blp_event(
  147.                  blp_cb[x].bsstate == BSDATA ? LDTIMER : LSTIMER ,
  148.                     &blp_cb[x], NULL, 0 );
  149.             }
  150.         }
  151.     }
  152. }
  153.  
  154.  
  155.             /* initialize blpcb data machine, ptrs etc */
  156. void cdecl  blp_data_init( blpcb )
  157. struct blpcb_struct *blpcb;
  158. {
  159.     blpcb->bdtxseq = blpcb->bdrxseq = blpcb->outstanding = 0 ;
  160.         blpcb->txpackets.next = NULL ;        /* clr linked list ptr */
  161.     blpcb->bdstate = BDIDLE ;        /* state -> IDLE */
  162. }
  163.  
  164.  
  165. void cdecl  send_blp_fr( blpcb, blp_cmd, info, len)
  166. struct blpcb_struct *blpcb;
  167. byte blp_cmd ;            /* cmd byte */
  168. byte *info;
  169. word len;
  170. {
  171.     byte    *insertptr ;            /* ptr to insert data */
  172.     byte    wkarea[AFTMAXFRAMESIZE];    /* work area to insert at */
  173.     int        newlen;
  174.     
  175.         newlen = len+2 ;        /* length is size of data +
  176.                            size of header */
  177.  
  178.         insertptr = wkarea ;    /* pointer we'll move data to */
  179.  
  180. #if LOOPBACK
  181.         *insertptr++ = blpcb->lcn ^ 0xC0; /* stick lcn in aft data fld */
  182. #else
  183.         *insertptr++ = blpcb->lcn ; /* stick lcn in aft data fld */
  184. #endif
  185.  
  186.         *insertptr++ = blp_cmd ;    /* and stick cmd byte too */
  187.         memcpy( insertptr, info, len ) ;    /* move data */
  188.  
  189.         dlc_data_cmd( wkarea, newlen );    /* give it to dlc */
  190. }
  191.  
  192. int cdecl  send_blp_datagram( lcn , info, len)
  193. byte lcn;
  194. byte *info;
  195. word len;
  196. {
  197.     byte    *insertptr ;            /* ptr to insert data */
  198.     byte    wkarea[AFTMAXFRAMESIZE];    /* work area to insert at */
  199.     int        newlen;
  200.  
  201.         newlen = len+2 ;        /* length is size of data +
  202.                            size of header */
  203.  
  204.         insertptr = wkarea ;    /* pointer we'll move data to */
  205.  
  206.         *insertptr++ = lcn ; /* stick lcn in aft data fld */
  207.  
  208.         *insertptr++ = UDATA ;    /* and stick cmd byte too */
  209.         memcpy( insertptr, info, len ) ;    /* move data */
  210.  
  211.         dlc_data_cmd( wkarea, newlen );    /* give it to dlc */
  212.         return( TRUE );        /* force OK return status */
  213. }
  214.  
  215.  
  216.     /* try to find blpcb for this lcn.  return *blpcb or NULL */
  217. struct blpcb_struct * cdecl find_lcn( lcn )
  218. byte lcn;
  219. {
  220.     int x;
  221.  
  222.     for ( x = 0 ; x < NLINKS ; x++ )
  223.                     /* if found, then break now */
  224.         if ( blp_cb[x].lcn == lcn && blp_cb[x].bsstate != BSIDLE )
  225.             break ;
  226.  
  227.             /* if x >= NLINKS then not found */
  228.     if ( x >= NLINKS )
  229.         return (NULL) ;        /* not found */
  230.     else
  231.         return (&blp_cb[x]) ;    /* else  ptr to it */
  232.  
  233. }
  234.  
  235.  
  236. void cdecl  send_cclrd(blpcb, bframe, len)
  237. struct blpcb_struct *blpcb;
  238. struct bframe_struct *bframe;
  239. word len;
  240. {
  241.     send_blp_fr( blpcb, CCLRD, NULL, 0);
  242. }
  243.  
  244. #if FALSE
  245. void cdecl  send_ca(blpcb, bframe, len)
  246. struct blpcb_struct *blpcb;
  247. struct bframe_struct *bframe;
  248. word len;
  249. {
  250.     send_blp_fr( blpcb, 0x03, NULL, 0);
  251. }
  252.  
  253. void cdecl  send_cca(blpcb,bframe,len)
  254. struct blpcb_struct *blpcb;
  255. struct bframe_struct *bframe;
  256. word len;
  257. {
  258.     send_blp_fr( blpcb, 0x05, NULL, 0);
  259. }
  260.  
  261. void cdecl  send_dnetack(blpcb,bframe,len)
  262. struct blpcb_struct *blpcb;
  263. struct bframe_struct *bframe;
  264. word len;
  265. {
  266. /*    send_blp_fr( blpcb, 0xF0 + blpcb->bdrxseq, NULL, 0); */
  267. }
  268. #endif
  269.  
  270. void cdecl  send_dack(blpcb,bframe,len)
  271. struct blpcb_struct *blpcb;
  272. struct bframe_struct *bframe;
  273. word len;
  274. {
  275.     send_blp_fr( blpcb, DACK + blpcb->bdrxseq, NULL, 0);
  276. }
  277.  
  278.  
  279. void cdecl  send_dbusy(blpcb,bframe,len)
  280. struct blpcb_struct *blpcb;
  281. struct bframe_struct *bframe;
  282. word len;
  283. {
  284.     send_blp_fr( blpcb, DBUSY + blpcb->bdrxseq, NULL, 0);
  285. }
  286.  
  287. void cdecl    send_cstrep(blpcb,bframe,len)
  288. struct blpcb_struct *blpcb;
  289. struct bframe_struct *bframe;
  290. word len;
  291. {
  292.     auto byte    dd[2] ;        /* store status values here */
  293.     
  294.     dd[0] = blpcb->bsstate; dd[1] = blpcb->bdstate;    /* store states */
  295.     send_blp_fr( blpcb, CSTREP , dd, 2);    /* send the packet */
  296. }
  297.  
  298. void cdecl send_cstenq(blpcb,bframe,len)
  299. struct blpcb_struct *blpcb;
  300. struct bframe_struct *bframe;
  301. word len;
  302. {
  303.     send_blp_fr( blpcb, CSTENQ , NULL , 0);
  304. }
  305.  
  306. void cdecl  ring_in(blpcb, bframe, len)
  307. struct blpcb_struct *blpcb;
  308. struct bframe_struct *bframe;
  309. word len;
  310. {
  311.     int    x;
  312.     struct    itm_struct *itm;
  313.  
  314.     /* need to assign blpcb cause the entered one is no good */
  315.  
  316.     /* find unused blpcb */
  317.     for ( x = 0 ; x < NLINKS ; x++ )
  318.         if ( blp_cb[x].bsstate == BSIDLE )    /* if unused */
  319.             break;                /* then break */
  320.  
  321.             /* if couldnt find an empty blpcb */
  322.     if ( x == NLINKS )
  323.     {
  324.                 /* then send call clr command */
  325.             /* if able to allocate intertask message for
  326.                one-shot call clear cmd */
  327.       if ( itm= (struct itm_struct *)
  328.             malloc(sizeof(struct itm_struct) + AFTMAXFRAMESIZE))
  329.       {
  330.         itm->itm_data[0] = bframe->lcn;
  331.         itm->itm_data[1] = 0x08 ;    /* cclr command */
  332.         itm->msg_len = 2 ;        /* two-bytes long */
  333.         aftt_send( itm ) ;        /*  send the frame */
  334.         free( (char *) itm );
  335.       }
  336.       else ;    /* else couldnt allocate, so drop on floor */
  337.     }
  338.     else
  339.     {        /* else empty blpcb found -- blp_cb[x] is empty */
  340.  
  341.         blp_cb[x].lcn = bframe->lcn;    /* store lcn in incoming
  342.                            blp_cb */
  343.         blp_data_init( &blp_cb[x] ) ;     /* init data machine */
  344.  
  345.         /* copy address */
  346.         strcpy( blp_cb[x].address,bframe->data);
  347.  
  348.             /*** SPECIAL CASE :
  349.                                 since no blpcb was found in the event
  350.                 handler, we need to force correct state
  351.                 & do retry/reset, as if event handler
  352.                 had done it from the table
  353.             ***/
  354.         blp_cb[x].bsstate = BSLCSETUP;
  355.         blp_timer_retry_reset( &blp_cb[x] );
  356.  
  357.             /* try to start upper level hander */
  358.         blp_cb[x].local_chan = blp_start_handler( &blp_cb[x] );
  359.             /** NOTE should do some checking here for
  360.                 inability to open upper channel, no? **/
  361.             /**NOTE2 -- in non-queued event struct, equate
  362.                aboove to local chan is unecessary **/
  363.  
  364. /*        send_ca( &blp_cb[x], NULL, 0 );    /* send call accepted */
  365.  
  366.      }
  367. }
  368.  
  369. void cdecl  collide(blpcb, bframe, len)
  370. struct blpcb_struct *blpcb;
  371. struct bframe_struct *bframe;
  372. word len;
  373. {
  374. #if LOOPBACK
  375.         /* these are defined in the handlers later on */
  376.     extern    struct blpcb_struct *blp_intfc[];
  377.     extern    byte    nextchan;
  378.  
  379.             /* loopback used for debug testing -
  380.                collissions construed to be loopbacks */
  381.     blpcb->bsstate = BSDATA ;        /* force supv'y data state */
  382.     blp_connected_handler( blpcb->local_chan) ;    /* tell upper
  383.                                level of cnct */
  384.     blp_intfc[nextchan++] = blpcb;    /* save ptr to blp cb */
  385.     blp_data_init( blpcb )    ;         /* init data machine */
  386.  
  387. #else
  388.             /* else normal proc is to inform of disc and
  389.                let state table take down the link */
  390.     blp_stop_handler( blpcb->local_chan ) ;        /* tell upper lev of
  391.                                loss */
  392. #endif
  393. }
  394.  
  395. void cdecl  answered(blpcb, bframe, len)
  396. struct blpcb_struct *blpcb;
  397. struct bframe_struct *bframe;
  398. word len;
  399. {
  400.     blp_connected_handler( blpcb->local_chan ) ;    /* tell upper
  401.                                level of cnct */
  402. /*    send_cca(blpcb,bframe,len); */
  403. }
  404.  
  405. void cdecl  caller_rdy(blpcb, bframe, len)
  406. struct blpcb_struct *blpcb;
  407. struct bframe_struct *bframe;
  408. word len;
  409. {
  410.     blp_connected_handler( blpcb->local_chan );
  411.     retrycc(blpcb,NULL,0);
  412. }
  413.  
  414. void cdecl  clr_reply(blpcb, bframe, len)
  415. struct blpcb_struct *blpcb;
  416. struct bframe_struct *bframe;
  417. word len;
  418. {
  419.     send_cclrd( blpcb, bframe, len );
  420.     blp_stop_handler( blpcb->local_chan );
  421. }
  422.  
  423. void cdecl  stopblp(blpcb, bframe, len)
  424. struct blpcb_struct *blpcb;
  425. struct bframe_struct *bframe;
  426. word len;
  427. {
  428.     struct    datapacket_struct *ptr;        /* use to free
  429.                            all outstanding pkts */
  430.     ptr = blpcb->txpackets.next ;    /* 1st packet, if any */
  431.  
  432.     while ( ptr )
  433.     {
  434.         free( (char *) ptr )    ;    /* free the buffer*/
  435.         ptr = ptr->next ;        /* and go to next one */
  436.     }
  437.     blpcb->txpackets.next = NULL ;        /* leave it null */
  438.  
  439.     blp_stop_handler( blpcb->local_chan );
  440. }
  441.  
  442. void cdecl  retryfail(blpcb, bframe, len)
  443. struct blpcb_struct *blpcb;
  444. struct bframe_struct *bframe;
  445. word len;
  446. {
  447.     blp_stop_handler( blpcb->local_chan );
  448. }
  449.  
  450. void cdecl  retrycs(blpcb, bframe, len)
  451. struct blpcb_struct *blpcb;
  452. struct bframe_struct *bframe;
  453. word len;
  454. {
  455.     int    x;
  456.     byte    *lastdr;
  457.     
  458.     lastdr = blpcb->address;
  459.     x = 0;
  460.  
  461.  
  462.     while ( *lastdr ) { lastdr++; x++ ;}
  463.     
  464.     if ( blpcb->email )
  465.         send_blp_fr( blpcb, CSEMAIL, blpcb->address, x );
  466.     else
  467.         send_blp_fr( blpcb, CS, blpcb->address, x );
  468.  
  469. /*    blpcb->timer = BLP_RETRY_TIME ;        /* */
  470. }
  471.  
  472. void cdecl  retrycc(blpcb, bframe, len)
  473. struct blpcb_struct *blpcb;
  474. struct bframe_struct *bframe;
  475. word len;
  476. {
  477.     send_blp_fr( blpcb, CCC, NULL, 0);
  478. /*    blpcb->timer = BLP_RETRY_TIME ;        /* */
  479. }
  480.  
  481. void cdecl  retrycclr(blpcb, bframe, len)
  482. struct blpcb_struct *blpcb;
  483. struct bframe_struct *bframe;
  484. word len;
  485. {
  486.     send_blp_fr( blpcb, CCLR, NULL, 0);
  487. /*    blpcb->timer = BLP_RETRY_TIME ;        /* */
  488. }
  489.  
  490. void cdecl  senddata(blpcb, bframe, len)
  491. struct blpcb_struct *blpcb;
  492. struct bframe_struct *bframe;
  493. word len;
  494. {
  495.     byte    ts;        /* transmit sequence # holder */
  496.     struct    datapacket_struct *pkt ;    /* point to data to send */
  497.  
  498.     ts = blpcb->bdtxseq ;            /* starting tx seq # */
  499.  
  500.     pkt = &blpcb->txpackets ;        /* points to oldest outstand
  501.                         ing packet, if !null */
  502.  
  503.         /* now traverse the linked list of pktzd xmit data */
  504.     while ( pkt->next )        /* while pkt in the list */
  505.     {
  506.         pkt = pkt->next ;        /* traverse to next pkt */
  507.                 /* send the packet */
  508.         send_blp_fr( blpcb, DDATA + ts, pkt->data, pkt->len );
  509.         ts = ( ( ts+1 ) & 15 );        /* next seq #, mod 16 */
  510.     }
  511.      /*endwhile */
  512.  
  513.     blpcb->timer = BLP_RETRY_TIME ;        /* restart timer */
  514.  
  515. }
  516.  
  517. void cdecl  dataproc(blpcb, bframe, len)
  518. struct blpcb_struct *blpcb;
  519. struct bframe_struct *bframe;
  520. word len;
  521. {
  522.     if ( (bframe->cmd & 15) == blpcb->bdrxseq )    /* if seq # matches */
  523.     {
  524.         if ( blp_data_handler( blpcb->local_chan, bframe->data,
  525.                     len-2 ) )    /* if upper level
  526.                                 toook the frame */
  527.         {
  528.                  /* mod16 bump*/
  529.             blpcb->bdrxseq = ( (blpcb->bdrxseq+1) & 15 );
  530.             send_dack( blpcb, NULL, 0 );    /*then send ack, */
  531.         }
  532.         else /* upper level could not take the frame */
  533.             blp_event( LDATABUSY, blpcb, NULL, 0);  /* so sig busy event */
  534.     }
  535.     else  /* else seq # didnt match */
  536.         send_dack( blpcb, NULL,0 );    /* send what we do hv */
  537. }
  538.  
  539. void cdecl  ackproc(blpcb, bframe, len)
  540. struct blpcb_struct *blpcb;
  541. struct bframe_struct *bframe;
  542. word len;
  543. {
  544.     byte    ackseq, nacked;        /* remote acks to seq ackseq, nacked
  545.                        # of packets */
  546.     struct    datapacket_struct *ptr;       /* use to delete packets from
  547.                     head of linked list */
  548.  
  549.     blpcb->retry_count = 0        ;     /* reset retry count */
  550.     
  551.     ackseq = ( bframe->cmd & 15 ) ;    /* strip off seq #, mod 16 */
  552.  
  553.     nacked = ( ackseq - blpcb->bdtxseq ) & 15 ;    /* he acks this many */
  554.  
  555.     if ( nacked > blpcb->outstanding )        /* if too many */
  556.         printf("*** error- too many acked\n");    /* need to do error!*/
  557.     else /* else no problem */
  558.     {
  559.       if ( blpcb->outstanding > 0 )        /* if packets were outsdng */
  560.       {
  561.  
  562. /*        if ( blpcb->bdtxseq == blpcb->bdrxseq )  /** if all acked WHEN 1 PACKET */
  563.         if ( (blpcb->outstanding-=nacked) == 0 )    /* if all ackd */
  564.             blp_event( LBLPACK, blpcb, NULL, 0) ;    /* then gen event */
  565.             
  566.         blpcb->bdtxseq = ackseq ;        /* update tx seq # */
  567.  
  568.             while ( nacked-- )        /* while packets left to release */
  569.         {
  570.         ptr = blpcb->txpackets.next->next ;
  571.                     /* link to 2d packet */
  572.  
  573.         free( (char *) blpcb->txpackets.next );    /* free 1st packet */
  574.         blpcb->txpackets.next = ptr ;    /* make 2d pkt the 1st in the
  575.                            head record */
  576.         } /*endwhile packets left to release*/
  577.        } /*endif outstanding packets */
  578.     } /*endif else */
  579. }
  580.  
  581.  
  582.       /** called from underlying DLC receiver **/
  583.     /** converts DLC frames into events and runs the event handler **/
  584. void cdecl  dlc_in_handler( bframe, len )
  585. struct bframe_struct *bframe;
  586. word len;
  587. {
  588.     byte    event ;        /* will convert blp cmd to event */
  589.     int    x ;
  590.     struct blpcb_struct *blpcb ;
  591.  
  592.         /* try to find the blpcb for this lcn */
  593.     blpcb = find_lcn( bframe->lcn );
  594.  
  595.     if ( !blpcb )        /* if not connected */
  596.         switch( bframe->cmd )    /* then what kind of cmd? */
  597.         {
  598.             case CS:
  599.                     /* kluge to get around need
  600.                        to know blpcb in event tables */
  601.                 ring_in( NULL, bframe, len );
  602.                 break ;
  603.             case CCLR:
  604.                     /* will need to respond here */
  605.                 break ;
  606.             case UDATA:    /* uncnctd data */
  607.                 break ; /* ignore for now */
  608.             default:
  609.                 break;     /* ignore others */
  610.         }
  611.     else
  612.     {
  613.       switch ( bframe->cmd )        /* on command, */
  614.       {
  615.         case CS: event = RCVD_CS; break;
  616. /*        case 0x03: event = RCVD_CA; break; */
  617.         case CCC: event = RCVD_CCC; break;
  618. /*        case 0x05: event = RCVD_CCCACK; break; */
  619.         case CCLR: event = RCVD_CCLR; break;
  620.         case CCLRD: event = RCVD_CCLRD; break;
  621.         case CSTENQ: event = LRXCSTENQ; break;
  622.         case CSTREP: event = LDTIMER; break;    /** fake LDTIMER xpire - 
  623.                                                     speeds up BLP */
  624.         default:
  625.                /* check for data states w/ variable lwr nibble*/
  626.             switch( bframe->cmd & 0xF0 )    /* strip of seq #*/
  627.             {
  628.                 case DDATA: event = LRXDATA; break;
  629.                 case DACK:
  630.                 case DBUSY: event = LRXACK; break;
  631.                 default:
  632.                     /* unknown cmd - err */
  633.                    printf("$%02X unknown cmd\n",bframe->cmd);
  634.                        return;
  635.                                    break;
  636.             }
  637.             break;
  638.       }
  639.             /* dispatch event only when blpcb is known */
  640.       blp_event( event, blpcb, bframe, len );
  641.  
  642.     } /* endif */
  643.  
  644.  
  645. }
  646.  
  647.  
  648. /*************************************************************
  649.         Interface : transport>blp
  650. **************************************************************/
  651.  
  652.         /** initiate a blp link; transport ref is chan # chan,
  653.             enpoint is at string @ address
  654.  
  655.             returns ptr to blpcb structure if able to initiate,
  656.             else returns NULL if error **/
  657.  
  658.  
  659. /*** start -- enter address[0] == '!' if call to email port desired ***/
  660.    struct blpcb_struct * cdecl
  661. blp_start_cmd( chan, address )
  662. byte chan;        /* transport ref*/
  663. char *address;        /* string w/ address */
  664. {
  665.     byte    lcn;        /* will need to select an lcn */
  666.     int    x;
  667.  
  668.  
  669.     strupr( address );        /* convert address to uppper case */
  670.                             /* 'cause  will have to look for tnc cmd setup*/
  671.                             
  672.     if ( ! strncmp( address, "TNCCMD", 6 ) )     /* if cmd port addrsd */
  673.         lcn = 0x70 ;        /* then select cmd port */
  674.     else
  675.         /* find an unused lcn */
  676.      for ( lcn = 0 ; lcn < 0x6e ; lcn++ )
  677.         if ( ! find_lcn( lcn ) )
  678.             break ;            /* break if unused found */
  679.  
  680.     if ( lcn == 0x6f )            /* if no lcn found */
  681.     {
  682.         return ( NULL );        /*  then return err */
  683.     }
  684.     else
  685.     {
  686.             /* find empty blpcb */
  687.         for ( x = 0 ; x < NLINKS ; x++ )
  688.             if ( blp_cb[x].bsstate == BSIDLE )
  689.             {
  690.                 /*** if email port, set flag and fix addr ****/
  691.                 if ( address[0] == '!' )
  692.                 {
  693.                     strcpy( address, address+1);    /* fix address, */
  694.                     blp_cb[x].email = TRUE ;        /* set email flag */
  695.                 }
  696.                     else blp_cb[x].email = FALSE;    /* else clear it */
  697.  
  698.  
  699.                     /* if empty blpcb found then */
  700.                        /* put called address in blpcb */
  701.                 atocall( blp_cb[x].address, address ) ;
  702.                  /** force one callsign only **/
  703. /*                blp_cb[x].address[6] |= 1 ; */
  704.                 blp_cb[x].address[7] = 0 ;
  705.  
  706.  
  707.                 blp_data_init( &blp_cb[x] ) ;
  708.                         /* init data machine */
  709.  
  710.                 blp_cb[x].local_chan = chan ;
  711.                 blp_cb[x].lcn = lcn ;
  712.                 blp_event( LSTART, &blp_cb[x], NULL, 0);
  713.                 return ( &blp_cb[x] );
  714.             }
  715.         /* if fell through here then couldnt find an empty blpcb;
  716.            return NULL for error */
  717.         return (NULL);
  718.     }
  719. }
  720.  
  721.  
  722.         /* send data on a particular link.  returns TRUE if
  723.            sent ok */
  724.  
  725. int  cdecl blp_data_cmd( blpcb, data, len )
  726. struct blpcb_struct *blpcb;
  727. byte *data;
  728. word len;
  729. {
  730.             /* vars needed to build and add to linked list */
  731.     struct    datapacket_struct *newpacket, *ptr;
  732.  
  733.     if ( blpcb->outstanding < BLP_MAX_OUTSTANDING /*if able to pktz more */
  734.       && blpcb->bsstate == BSDATA             /* and in a data state */
  735.       && ( newpacket = (struct datapacket_struct *)
  736.                             malloc(sizeof(struct datapacket_struct)) ) )
  737.             /* and able to allocate then */
  738.     {
  739.         newpacket->len = len ;        /* set up len field */
  740.         memcpy(newpacket->data,data,len);    /* set up data */
  741.         newpacket->next = NULL ;    /* init link field */
  742.  
  743.             /* now add to tail of linked list */
  744.         ptr = &blpcb->txpackets ;    /*1st, ptt to hdr dummy struct */
  745.         while ( ptr->next )           /* while not at end of list */
  746.             ptr = ptr->next ;    /* traverse */
  747.  
  748.             /*now merely put ptr to new packet at end of list link*/
  749.         ptr->next = newpacket;
  750.         blpcb->outstanding++;
  751.  
  752.             /* signal new data */
  753.         blp_event( LNEWDATA, blpcb, NULL, 0);
  754.  
  755.         return( TRUE );
  756.     } else  return (FALSE);
  757.  
  758. }
  759.  
  760. void blp_stop_cmd( blpcb )
  761. struct blpcb_struct *blpcb;
  762. {
  763.     blp_event( LSTOP, blpcb, NULL, 0 );
  764. }
  765.  
  766. void blp_status_cmd( blpcb )
  767. struct blpcb_struct *blpcb;
  768. {
  769.     send_cstenq( blpcb, NULL, 0);
  770. }
  771.  
  772. /*************************************************************
  773.         Interface : blp>transport
  774. **************************************************************/
  775.  
  776.         /* variable - hold blpcb pointers for each channel */
  777.  
  778.     struct    blpcb_struct *blp_intfc[NLINKS+1] ;
  779.  
  780.     byte nextchan = 0 ;    /* just assign local chans in order */
  781.  
  782. byte cdecl blp_start_handler( blpcb )
  783. struct blpcb_struct *blpcb;
  784. {
  785.  
  786.     char    temp[80];    /* address temporarily built here */
  787.  
  788.     calltoa( temp, blpcb->address);    /* convert address to ascii */
  789.  
  790.     printf("\nCall for %s accepted on channel %d", temp, nextchan );
  791.  
  792.     blp_intfc[nextchan] = blpcb;    /* save ptr to blp cb */
  793.  
  794.     blpcb->local_chan = nextchan;    /* NEED to set this here since
  795.                        events are not queued &
  796.                        next transition requires it
  797.                        to be */
  798.         /*** Call for connected immediately since it's local */
  799.     blp_event( LCNCTD, blpcb, NULL, 0 );    /* generate the event */
  800.  
  801.     return( nextchan++ )    ;    /* return chan # (& bump it) */
  802. }
  803.  
  804.  
  805. void cdecl blp_connected_handler( chan )
  806. byte chan;
  807. {
  808.     printf("\nConnected on channel %d", chan );
  809. }
  810.  
  811. void cdecl blp_stop_handler( chan )
  812. byte chan;
  813. {
  814.     printf(" Channel %d stopped\n", chan);
  815. }
  816.  
  817.         /*** should return TRUE if able to accept data ***/
  818. int cdecl blp_data_handler( chan, data, len )
  819. byte chan, *data;
  820. word len;
  821. {
  822.     printf("\nData on chan %d:",chan);
  823.     while ( len-- )
  824.         putchar(*data++);
  825.     putchar('\n');
  826.     return( TRUE );        /* always return true in this intfc */
  827. }
  828.  
  829.  
  830.                     /* get state tables */
  831. #include    "blptables.c"
  832.